package org.jvm.nativemethod.methods.java.io;

import org.jvm.nativemethod.NativeMethodRegister;
import org.jvm.rtda.Object;
import org.jvm.rtda.thread.*;
import org.jvm.util.JvmUtil;

import java.io.*;

/**
 * @author 海燕
 * @date 2023/2/26
 */
public class FileInputStreamMethod extends NativeMethodRegister {

    public static void init() throws NoSuchMethodException {
        register("java/io/FileInputStream", "available0", "()I", FileInputStreamMethod.class.getDeclaredMethod("available0", Frame.class));
        register("java/io/FileInputStream", "close0", "()V", FileInputStreamMethod.class.getDeclaredMethod("close0", Frame.class));
        register("java/io/FileInputStream", "readBytes", "([BII)I", FileInputStreamMethod.class.getDeclaredMethod("readBytes", Frame.class));
        register("java/io/FileInputStream", "open0", "(Ljava/lang/String;)V", FileInputStreamMethod.class.getDeclaredMethod("open0", Frame.class));
    }

    public static void available0(Frame frame) {
        frame.getOperandStack().pushInt(1);
    }

    public static void close0(Frame frame) {
        LocalVars localVars = frame.getLocalVars();
        //FileInputStream实例
        Object fis = localVars.getThis();
        FileInputStream fileInputStream = (FileInputStream) fis.getExtra();
        try {
            fileInputStream.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static void readBytes(Frame frame) {
        LocalVars localVars = frame.getLocalVars();

        Object fis = localVars.getThis();
        Object buf = localVars.getRef(1);
        byte[] bytes = buf.bytes();
        int off = localVars.getInt(2);
        int len = localVars.getInt(3);
        FileInputStream fileInputStream = (FileInputStream) fis.getExtra();
        try {
            int n = fileInputStream.read(bytes, off, len);
            frame.getOperandStack().pushInt(n);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 从磁盘加载文件到内存
     *
     * @param frame
     */
    public static void open0(Frame frame) {
        LocalVars localVars = frame.getLocalVars();
        //FileInputStream实例
        Object fis = localVars.getThis();
        //文件名
        Object name = localVars.getRef(1);

        String fileName = JvmUtil.javaStringToJvmString(name);
        try {
            FileInputStream fileInputStream = new FileInputStream(fileName);
            fis.setExtra(fileInputStream);
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

}
